#include "Task.hpp"

// 频道：父进程往哪一个频道保存的 写端fd写入内容 就可以控制 对应pid的子进程执行任务
class Channel
{
public:
    Channel(int wfd, pid_t who) : _wfd(wfd), _who(who)
    {
    }
    int ret_wfd()
    {
        return _wfd;
    }
    pid_t ret_who()
    {
        return _who;
    }

private:
    int _wfd;   // 写端fd
    pid_t _who; // 子进程pid
};

class ProcessPool
{
public:
    ProcessPool()
    {
    }

    // 创建k个匿名管道
    void add_channel(int k, std::function<void(int, int)> call_back)
    {
        while (k--)
        {
            int fds[2];
            pipe(fds);
            pid_t n = fork();
            if (n == 0)
            {
                // 关闭子进程中 继承的多余写端fd
                for (int i = 0; i < processnum; i++)
                    close(channels[i].ret_wfd());
                // 子进程执行回调函数
                call_back(fds[0], fds[1]);
            }
            close(fds[0]);
            // 父进程将 写端fd和子进程pid 写入新频道
            channels.push_back({fds[1], n});
            processnum++;
        }
    }

    int ret_processnum()
    {
        return processnum;
    }

    // 打印进程池的信息
    void processpool_print()
    {
        int i = 0;
        for (auto it : channels)
        {
            std::cout << "channel " << i << ':' << it.ret_wfd() << '/' << it.ret_who() << std::endl;
            i++;
        }
        printf("\n");
    }

    // 轮询向各个管道的写端写入内容，总共写入k次
    void channel_write(int k)
    {
        std::string str;
        int j = 0;
        while (k--)
        {
            str.clear();
            std::getline(std::cin, str);
            write(channels[j].ret_wfd(), str.c_str(), str.size());
            j = (j + 1) % processnum;
        }
    }

    // 关闭指定写端
    void close_wfd(int j)
    {
        close(channels[j].ret_wfd());
    }

    // 回收子进程
    void wait_process(int j)
    {
        waitpid(channels[j].ret_who(), nullptr, 0);
    }

private:
    std::vector<Channel> channels;
    int processnum = 0;
};